package messaging;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import log.Logger;

import node.NodeManager;

/**
 * Does the token message processing.
 * @author Team 4
 * @version 1th June 2013
 */
public class TokenNodeMessage
{
  /**
   * Store the token packet.
   */
  private final TokenPacket my_token_packet;
  /**
   * Stores the node id which is processing the message.
   */
  private final int my_node_id;
  /**
   * Stores the node manager.
   */
  private final NodeManager my_node_manager;
  /**
   * stores if it has to send it across.
   */
  private boolean my_send_across = true;
  /**
   * Instantiates the token packet.
   * @param the_token_packet : stores the token packet
   * @param the_process_node : stores the node no which is processing this message
   * @param the_node_manager : stores the node manager
   */
  public TokenNodeMessage(final TokenPacket the_token_packet, final int the_process_node,
                          final NodeManager the_node_manager)
  {
    my_token_packet = the_token_packet;
    my_node_id = the_process_node;
    my_node_manager = the_node_manager;
  }
  /**
   * Returns true if it has to send across the ring.
   * @return whether it is has to send the token to next node.
   */
  public boolean isMySendAcross()
  {
    return my_send_across;
  }
  /**
   * Returns token packet.
   * @return the token packet.
   */
  public TokenPacket getTokenPacket()
  {
    return my_token_packet;
  }
  /**
   * processes the message. 
   */
  public void processMessage()
  {
    if (my_node_id == my_token_packet.getMyNodeId())
    {
      my_send_across = false;
      return;
    }
    else 
    {
      if (my_token_packet.getMyTokenType() == TokenType.COUNT)
      {
        Logger.writeContent("LOG-"+this.my_node_id + ".txt", "Got a request for total count in ring"); 
        int count = my_token_packet.getMyKeyCount();
        final Map<String, Serializable> firstkey = 
            my_node_manager.node_stubs.get(this.my_node_id).my_map;
        final Set<String> string_value = firstkey.keySet(); 
        count += string_value.size(); 
        my_token_packet.setMyKeyCount(count);
        Logger.writeContent("LOG-"+this.my_node_id  + ".txt", "Total Count Value: " + my_token_packet.getMyKeyCount());
      
      }
      else if (my_token_packet.getMyTokenType() == TokenType.ACTUALCOUNT)
      {
        Logger.writeContent("LOG-"+ this.my_node_id + ".txt", "Got a request for actual node in ring");
        if (my_node_id == my_node_manager.actual_node_number)
        {
          ArrayList<Integer> count = my_token_packet.getMyActualCount();
          count.add(my_node_id);
          my_token_packet.setMyActualCount(count);
        }
        Logger.writeContent("LOG-"+this.my_node_id  + ".txt", "Actual Count list: " + my_token_packet.getMyActualCount().toString());
      }
      else if (my_token_packet.getMyTokenType() == TokenType.FIRSTKEY)
      {
        Logger.writeContent("LOG-"+this.my_node_id + ".txt", "Got a request for first key in ring");
        final Map<String, Serializable> firstkey = 
            my_node_manager.node_stubs.get(this.my_node_id).my_map;
        final Set<String> string_value = firstkey.keySet(); 
        final Iterator i = string_value.iterator();
        String first_value = my_token_packet.getMyFirstKey();
        if ((!string_value.isEmpty()) || string_value != null)
        {
          if (first_value == null & i.hasNext())
          {
            first_value = i.next().toString();
          }
          while (i.hasNext())
          {
            final String set_string = i.next().toString();
            if (set_string.compareTo(first_value) < 0)
            {
              first_value = set_string; 
            }
          }
        }
        
        my_token_packet.setMyFirstKey(first_value);
        Logger.writeContent("LOG-"+this.my_node_id  + ".txt", "First Key Value: " + my_token_packet.getMyFirstKey());
        
      }
      else if (my_token_packet.getMyTokenType() == TokenType.LASTKEY)
      {
        Logger.writeContent("LOG-"+this.my_node_id  + ".txt", "Got a request for last key in ring");
        final Map<String, Serializable> lastkey =
            my_node_manager.node_stubs.get(this.my_node_id).my_map;
        final Set<String> string_value = lastkey.keySet(); 
        final Iterator i = string_value.iterator();
        String last_value = my_token_packet.getMyLastKey();
        if ((!string_value.isEmpty()) || string_value != null)
        {
          if (last_value == null && i.hasNext())
          {
            last_value = i.next().toString();
          }
        
          while (i.hasNext())
          {
            final String set_string = i.next().toString();
            if (last_value.compareTo(set_string) < 0)
            {
              last_value = set_string; 
            }
          }
        }
        my_token_packet.setMyLastKey(last_value);
        Logger.writeContent("LOG-"+this.my_node_id  + ".txt", "Last Key Value: " + my_token_packet.getMyLastKey());
      }
      
    }
  }
  
}
